﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml;
using umbraco;
using AutoFolders.Providers;
using System.Reflection;

namespace AutoFolders
{
    public class AutoFolderSettings
    {
        private Dictionary<string, AutoFolderSetting> m_autoFolders;
        private Dictionary<string, IFolderProvider> m_folderProviders;
        private static AutoFolderSettings m_autoFolderSettings;

        public static AutoFolderSettings Instance
        {
            get {
                if (m_autoFolderSettings == null)
                    m_autoFolderSettings = new AutoFolderSettings();

                return m_autoFolderSettings;
            }
        }

        private AutoFolderSettings()
        {
            m_autoFolders = new Dictionary<string, AutoFolderSetting>();
            m_folderProviders = new Dictionary<string, IFolderProvider>();

            // Load from XML settings file
            LoadXmlSettingsFile();
        }

        private void LoadXmlSettingsFile()
        {
            XmlDocument settingsFile = new XmlDocument();
            settingsFile.Load(HttpContext.Current.Server.MapPath(GlobalSettings.Path + "/../config/autofolders.config"));

            // Load all IFolderProviders
            foreach (XmlNode xsltEx in settingsFile.SelectSingleNode("/settings/folderProviders"))
            {
                if (xsltEx.NodeType == XmlNodeType.Element)
                {
                    // load the extension assembly
                    string extensionFile = HttpContext.Current.Server.MapPath(String.Format("{0}/..{1}.dll",
                                                                              GlobalSettings.Path,
                                                                              xsltEx.Attributes["assembly"].Value));
                    Assembly extensionAssembly;
                    try
                    {
                        extensionAssembly = Assembly.LoadFrom(extensionFile);
                    }
                    catch (Exception ex)
                    {
                        throw new Exception(String.Format("Could not load assembly {0} for AutoFolders provider {1}. Please check config/autofolder.config.",
                                                          extensionFile, xsltEx.Attributes["alias"].Value), ex);
                    }

                    // load the extension type
                    Type extensionType = extensionAssembly.GetType(xsltEx.Attributes["type"].Value);
                    if (extensionType == null)
                        throw new Exception(String.Format("Could not load type {0} ({1}) for AutoFolders provider {1}. Please check config/autofolder.config.",
                                  xsltEx.Attributes["type"].Value, extensionFile, xsltEx.Attributes["alias"].Value));

                    IFolderProvider folderProvider = Activator.CreateInstance(extensionType) as IFolderProvider;

                    // Load additional properties
                    foreach (XmlNode propertyNode in xsltEx.SelectNodes("property"))
                    {
                        folderProvider.Properties.Add(propertyNode.Attributes["alias"].Value, propertyNode.InnerText);
                    }


                    // create an instance and add it to the extensions list
                    m_folderProviders.Add(xsltEx.Attributes["alias"].Value, folderProvider);
                }

            }

            // Load in effected doc types
            foreach (XmlNode xsltEx in settingsFile.SelectSingleNode("/settings/autoFolders"))
            {
                if (xsltEx.NodeType == XmlNodeType.Element)
                {
                    AutoFolderSetting autoFolderSetting = new AutoFolderSetting();
                    autoFolderSetting.DocType = xsltEx.Attributes["docType"].Value;
                    autoFolderSetting.FolderProviderAlias = xsltEx.Attributes["folderProviderAlias"].Value;

                    // Add ApplicableParents
                    if (xsltEx.Attributes["rootFolders"] != null)
                    {
                        string rootFolders = xsltEx.Attributes["rootFolders"].Value;
                        if (!String.IsNullOrEmpty(rootFolders))
                        {
                            autoFolderSetting.RootFolders = rootFolders;
                        }
                    }

                    // Add TruncatedFolderRoot
                    if (xsltEx.Attributes["truncatedFolderUrl"] != null)
                    {
                        string truncatedFolderUrl = xsltEx.Attributes["truncatedFolderUrl"].Value;
                        if (!String.IsNullOrEmpty(truncatedFolderUrl))
                        {
                            autoFolderSetting.TruncatedFolderUrl = truncatedFolderUrl;
                        }
                    }

                    // Add TruncatedFolderRoot
                    if (xsltEx.Attributes["folderDocType"] != null)
                    {
                        string folderDocType = xsltEx.Attributes["folderDocType"].Value;
                        if (!String.IsNullOrEmpty(folderDocType))
                        {
                            autoFolderSetting.FolderDocType = folderDocType;
                        }
                    }

                    // Load in RootFolder
                    /*
                    if (xsltEx.Attributes["moveToFirstParent"] != null)
                    {
                        string moveToFirstParent = xsltEx.Attributes["moveToFirstParent"].Value;
                        if (!String.IsNullOrEmpty(moveToFirstParent))
                        {
                            autoFolderSetting.MoveToFirstParent = (moveToFirstParent=="true");
                        }
                    }
                     * */


                    if (!m_folderProviders.ContainsKey(autoFolderSetting.FolderProviderAlias))
                        throw new Exception(String.Format("Could not associate autosetting '{0}' with provider '{1}' as provider doesn't exist. Please check config/autofolders.config.",
                                  autoFolderSetting.DocType, autoFolderSetting.FolderProviderAlias));

                    autoFolderSetting.FolderProvider = m_folderProviders[autoFolderSetting.FolderProviderAlias];

                    // create an instance and add it to the extensions list
                    m_autoFolders.Add(autoFolderSetting.DocType, autoFolderSetting);
                }

            }

        }

        public bool IsEffectedDocType(string docTypeAlias)
        {
            return m_autoFolders.ContainsKey(docTypeAlias);
        }

        public AutoFolderSetting GetSettings(string docTypeAlias)
        {
            if (m_autoFolders.ContainsKey(docTypeAlias))
            {
                return m_autoFolders[docTypeAlias];
            }
            else
            {
                return null;
            }
        }

        public IFolderProvider GetFolderProviderByParentUrl(string urlRoot)
        {
            foreach (AutoFolderSetting autoFolderSetting in m_autoFolders.Values)
            {
                if (autoFolderSetting.TruncatedFolderUrl == urlRoot)
                {
                    return autoFolderSetting.FolderProvider;
                }
            }

            return null;
        }
    }
}
